.TH "display-x" 7 "2009-08-05" "libggi-current" GGI
.SH NAME
\fBdisplay-x\fR : Displays to an X11 server
.SH SYNOPSIS
.nb
.nf
display-x: [ [-inwin=<winid>|root] | [-screen=<screenidx>] ]
           [-fullscreen] [-keepcursor] [-noaccel] [-nobuffer]
           [-nocursor] [-nodbe] [-nodga] [-noevi] [-noinput]
           [-nomansync] [-noshm] [-novidmode] [-physz=<sizex>,<sizey>[dpi]]
           [<display>]
.fi

.SH DESCRIPTION
\fBdisplay-x\fR displays a GGI application via an X11 server.  The server
may be local or remote, and options are provided to tune performance
to various scenerios.  In normal operation, a new X11 window is
opened, solid fill primitives and copybox are accelerated by the
server, and a backbuffer is kept client-side for content fills
(e.g. ggiPut* functions) and to restore data when an application has
been exposed after being concealed by another window.

\f(CWCtrl-Alt-m\fR toggles mouse grabbing in the new window.  It will try
to emulate a \fIrelative\fR mouse device, i.e. one that can be moved
arbitrarily far in any direction without ever leaving the window.
This is useful for game controls, where losing focus is generally
undesireable.  Note that grabbing must be turned off in order to leave
the window.
.SH OPTIONS
.TP
\fIdisplay\fR
The X display to connect to, otherwise defaults to the display
specified in \fBDISPLAY\fR.

.TP
\f(CW-fullscreen\fR
Turns on the fullscreen mode. Default mode is the windowed mode.
In fullscreen mode, the dga helper is tried first if not disabled
by -nodga or failed for some reason. Then the vidmode helper is
tried. When this fails, then the target falls back to the windowed
mode. Note, the -inwin option has no effect with fullscreen.

.TP
\f(CW-noaccel\fR
All rendering is performed in the client-side backbuffer, and then
sent to the server; no server-side accelerated graphics
operations are used.  This will signifigantly slow down certain
graphics applications, but for applications that use directbuffer
and asynchronous mode extensively the effect will not be
noticeable.  The only real reason to use this option, however, is
to eliminate artifacts caused by incorrectly implemented X11
hardware drivers.

.TP
\f(CW-nobuffer\fR
No client-side backbuffer is kept.  This may result in lost data
when the LibGGI application is obscured by other windows.  This
data loss can be minimized by enabling backing store in the X11
server.  Using this option will cause operations which must read
back framebuffer data to be much slower, but on the other hand can
result in a slight speed gain for certain graphics primitives.  It
is best used when resources are severely limited on the client
side, and with applications that do not perform frequent ggiPut*
operations.
Note, with this option evExpose events are passed to the
application (Otherwise, they are internally grabbed to update the
backbuffer).

.TP
\f(CW-nodbe\fR
Use of the X11 DBE extension to provide buffered frame support is
disabled.
.RS
\fBNote:\fR
Currently DBE extension support has not been completed.
.RE

.TP
\f(CW-nodga\fR
Use of the XFree86-DGA extension to provide direct framebuffer access
is disabled.  Some implementations of the XFree86-DGA extension may cause
system lockups.  Use this option to prevent such occurrances.

.TP
\f(CW-noevi\fR
Use of the X11 Extended Visual Information extension to identify
visuals which are exclusively used for overlay/underlay is
disabled.

.TP
\f(CW-noinput\fR
X events sent to the window are not captured and merged with any
other LibGII input sources.  This allows one to take input from
raw devices without receiving duplicate events should X also be
configured to use the device.

.TP
\f(CW-nocursor\fR, \f(CW-keepcursor\fR
Normal behavior of display-x is to create a small dot mouse cursor
pixmap which is visible when the mouse is positioned over the
window containing the visual.  This goes away when using mouse
grabbing as described above, but otherwise can get in the way of
mouse cursors implemented by the application.  With the former
option, the X mouse cursor will be invisible when it is over the
visual, with the latter, the cursor from the root window is used
unaltered.  If both options are supplied, the latter takes
precedence.

.TP
\f(CW-nomansync\fR
Use of the mansync helper library to periodically flush backbuffer
contents to the X11 server is disabled.  This, of course, will
result in incorrect behavior of applications that use synchronous
mode.

.TP
\f(CW-noshm\fR
Use of the MIT-SHM extension to speed data transfer between
clients and servers which are running on the same machine is
disabled.  Normally it is not necessary to use this option, as use
of the MIT-SHM extension is disabled automatically if it appears
to be nonfunctional.

.TP
\f(CW-inwin=<winid>|root\fR
Run in already-existing window with id \fIwinid\fR.  This can be
used to embed a LibGGI application into an X11 application.  The
value should be an X11 window ID expressed as a "0x" prefixed
hexadecimal number.  The special string "root" will cause the
application to run in the root window of the selected screen (or
the default screen if no explicit selection has been made.)  Note
that in the root window, you may need to explicitly select a LibGII
input source using the \fBGGI_INPUT\fR environment variable as the
window manager will absorb all events sent to the root window.
Some features (currently frames and virtual areas) may not work in
root windows.  On the other hand, when using the root window other
features like direct framebuffer access and video hardware mode
selection may be available which are not available when the
application is running in a normal window.

.TP
\f(CW-novidmode\fR
Use of the X11 Vidmode extension to change video timing in full-screen
modes is disabled.  Some implementations of the Vidmode extension may cause
system lockups.  Use this option to prevent such occurrances.

.TP
\f(CW-physz=<sizex>,<sizey>[dpi]\fR
This option will override the physical screen size reported by the
X server, which affects applications which wish to remain
resolution independent.  \fIsizex\fR,:p:\fBsizey\fR are the x,y size of
the entire screen (not just the X window containing the visual) in
millimeters, unless the optional \f(CWdpi\fR string is affixed, in
which case, they represent resolution in dots-per-inch. Yes, there
are two equals signs there, for reasons of compatibility with
other targets.

.TP
\f(CW-screen=<screenidx>\fR
The screen to run on.  Normally the biggest/deepest screen
compatible with the requested mode will be chosen; with this
option only the screen specified by \fIscreenidx\fR will be
considered.

.PP
.SH "CLIFF NOTES" ON NEW X TARGET
The old X target rendered all primitives in a RAM backbuffer, and then
copied the entire backbuffer periodically using the mansync helper to
the X screen.  This caused a lot of wasted bandwidth.  However, since
the bandwidth was being wasted anyway, LibGGIMISC splitline support
was a simple hack that added nearly no complexity.

The old Xlib target had no RAM backbuffer and rendered all primitives
using Xlib calls.  This caused very slow performance when a lot of
individual pixels were being drawn one at a time, and slow performance
on operations which got pixel data back from the visual, since it had
to be fetched back over the wire.  Also, this precluded the use of the
directbuffer on the xlib target.

The new X target in its default mode maintains both a RAM backbuffer
on the client side, and uses Xlib primitives to draw on the server
side.  When a primitive, such as a drawbox, can use an Xlib function,
the command is dispatched to the X server and the data in the RAM
buffer is updated using a software renderer.  For operations such as
putbox, the RAM buffer is updated first, and then synced to the X
server.  Unlike the old target, the new target keeps track of a "dirty
region" and only syncs the area affected since the last time a
synchronization occured.  This dirty-region tracking only keeps track
of one rectangular dirty area.  A helper library that keeps track of
more than one rectangle could be implemented to improve performance of
display-X and any other similarly designed display target.  To be most
flexible such a target should take weighted parameters representing
the cost of transferring data (per byte) from the backbuffer, and the
per-operation cost of initiating such a transfer, which would alter
its strategy as to how many regions are maintained and how much they
overlap.

The old X target's RAM buffer was implemented using the X target's
drawops hooks -- that is, the RAM buffer was essentially a
re-implementation of display-memory with the extra facilities to sync
to the X server built in.  The new target capitalizes on some
improvements made in display-memory, and instead it opens and loads a
child display-memory visual which takes care of finding software
renderers for the RAM buffer.  The main drawops of the new target
dispatch the X server commands and call the child's corresponding
software drawops to ensure consistent state of the RAM buffer vs the X
window.  This must be done such that any requests to get data from the
RAM backbuffer are not processed until the RAM backbuffer is up to
date, and any flushes from the backbuffer are not processed until the
backbuffer is up to date.  There's a lot of locking intricacy to
ensure this level of consistency.

The basic synchronization operation is accomplished by the flush
function, which is the function loaded on the xpriv \fBflush\fR member
hook.  The flush hook function is called:
.IP 1 4
When the mansync helper decides it is time to refresh the screen.
.IP 2 4
After a primitive, if the visual is in synchronous rendering mode.
.IP 3 4
When an expose or graphicsexpose event is sent from the server.
This means the server has discarded data that was concealed by
another window or by the edge of the screen, and the data must be
resent from the client.
.PP
...in the last case the whole area that must be refreshed is sent
again by the client.  In the first two cases only the dirty area is
sent, except when the application is holding the directbuffer writing
resource, in which case the whole area must be synced because there is
no way for the target to tell what the user has modified.  Holding the
directbuffer write resource open when the display is in synchronous
mode or when also sending primitives will result in bad performance.
There's no reason to do so on any target, so don't.

Unfortunately some XFree86 drivers are buggy, and when you render an
accelerated primitive which overlaps an area which is not visible to
the user, the driver fails to update the backing store (it only draws
the clipped primitive using accelarated functions and does not complete
the job by calling the software renderer to update the backing store.)
Most people will not be affected by this bug, however.

The new X target implements gammamap (DirectColor), unlike the old
targets.

The new X target is best used with backing store turned on in the
server.  When backing store is not turned on, primitives which are
clipped to the visual area but still in the virtual area may be slower
than the old target, since data will be sent to the server hoping it
will be stored in the backing store.  Likewise when a full-screen
flush occurs the entire virtual area data is sent.  The target could
be optimized not to send this data when it detects that there is no
backing store available in the server.

Either the RAM backbuffer or the X primitives can be disabled via
target options, which will cause emulation of the old X (\f(CW-noaccel\fR) and
Xlib (\f(CW-nobuffer\fR) targets, with a couple of notable exceptions:
.RS
The old X and Xlib targets opened a window and drew directly into
it.  The old Xlib target did not implement support for
ggiSetOrigin.  As noted above the old X target used a hack that
didn't cost much when compared to the cost of syncing the
backbuffer periodically.  The new target implements ggiSetOrigin
by creating a parent window, then creating a child window inside
the parent window.  Thus the child window can be moved around
inside the parent window, and the parent window will clip the
displayed data to the right size.  This is much more efficient
than the old way when the server is keeping a backing store (which
it sometimes does "in secret" even when the backing store
functionality in the server is turned off.)
.RE
Unfortunately many window managers seem to be buggy, and do not
install the colormap of a child window when a mouse enters it.  This
causes palette and gammamap to be messed up.  Since so many
window managers fail to implement the behavior described in the Xlib
manpages, a workaround needs to be added which will not use the child
window (this part is easy enough since the -inwin=root option already
implements a child-less rendering) and either disables ggiSetOrigin
support, or uses a better version of the old display-x target's
creative blitting to emulate setorigin support.

LibGGIMISC's splitline support for the original X display was broken
by the new child-window stuff as well.  In order to implement
splitline support, libggimisc must implement a new set of primitives
for the new display X that uses two child windows to produce the
splitline effect.  This complicates a lot of the primitives, so the
code is best isolated in LibGGIMISC so any bugs or performance issues
in it do not affect vanilla LibGGI users who have no need for
splitline.  It would probably be best if the special renderers were
only loaded on the first call to ggiSetSplitline, so that when
LibGGIMISC implements support for the XSync extension, users who are
not using splitline do not pay a performance penalty for using XSync.

The child window may also be to blame for the fact that a window which
is focused, but not moused over, stops receiving keyboard events.
Reworking the X input target to take it's keyboard events from the
parent window instead of the child window (mouse and
expose/graphicsexpose events must still come from the child window)
would be the needed fix.

The new target tries to remove dl dependencies by creating a separate
module file for any X extensions used.  Because of some deficiencies
in the X module system (there is no way to cleanly unload a module)
some kludges have had to be made when a module is loaded but gleaned
to be nonpresent, then unloaded.  This won't effect most people.

However, a more common problem will be seen because X does not give us
any way to determine if the XSHM extension will work -- it tells us
whether the server has XSHM, but it does not tell us whether the
client and server can share memory segments.  Thus, when running a
remote client, it may be necessary to manually disable XSHM support
with the -noshm target option.

Anyway, I hope this is helpful to any intrepid soul which decides to
fondle this code :-) (Brian S. Julin)
.SH FEATURES
.IP \(bu 4
DirectBuffer always available.
.IP \(bu 4
Accelerated
.IP \(bu 4
Multiple frames except for root window
.IP \(bu 4
Panning except for root window
.IP \(bu 4
Support Gammamap
.PP
